﻿using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using tju.cme.BookStore2024.webapi.Models.EF;
using tju.cme.BookStore2024.webapi.Models.Tools;
using tju.cme.BookStore2024.webapi.Models.ViewModels.Author;

namespace tju.cme.BookStore2024.webapi.Services
{
    /// <summary>
    /// T011author相关服务
    /// </summary>
    public class AuthorServices(BookStore2024Context context, IConfiguration configuration)
    {
        public async Task<IEnumerable<T011author>> GetAllAuthorsAsync()
        {
            return await context.T011authors.ToListAsync();
        }


        /// <summary>
        /// 作者注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task AuthorRegisterAsync(AuthorRegisterModel model)
        {
            if (context.T011authors.Any(m => m.UserName.ToUpper() == model.UserName.ToUpper()))
                throw new Exception("用户名已被注册"); //该错误提示用户是否可见？

            var newItem = new T011author()
            {
                Id = Guid.NewGuid(),
                UserName = model.UserName,
                Password = Util.MD5(model.Password),
                NickName = model.NickName,
                AuthorProfile = model.AuthorProfile,
                //TelephoneNumber = model.TelephoneNumber,
            };

            await context.T011authors.AddAsync(newItem); //添加到内存
            await context.SaveChangesAsync(); //添加到数据库   包含事务操作
        }

        /// <summary>
        /// 作者登录
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<JwtSecurityToken> AuthorLoginAsync(AuthorLoginModel model)
        {
            //取出与填入用户名相同的用户信息放进item
            var item = await context.T011authors.FirstOrDefaultAsync(m => m.UserName == model.UserName);
            if (item == null)
                throw new Exception("错误的帐号密码");
            var pwd = Util.MD5(model.Password);
            if (model.UserName == item.UserName && pwd == item.Password.ToUpper())
            {
                var claims = new List<Claim>
                {
                    //一个对用户ID和姓名的集合
                    new Claim(ClaimTypes.Sid, item.Id.ToString()),
                    new Claim(ClaimTypes.Name, item.UserName),
                    new Claim(ClaimTypes.Role, "Author")
                };


                //sign the token using a secret key.This secret will be shared between your API and anything that needs to check that the token is legit.
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtSecurityKey"]!));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var token = new JwtSecurityToken(
                    claims: claims,//凭据
                    expires: DateTime.Now.AddMinutes(30), //过期时间 30min后失效
                    signingCredentials: creds);  //加密后的密码
                return token;
            }
            throw new Exception("错误的帐号密码");
        }

        /// <summary>
        /// 为作者分配管理员
        /// </summary>
        /// <param name="authorId"></param>
        /// <param name="adminId"></param>
        /// <returns></returns>
        public async Task AssignAdminAsync(Guid authorId, Guid adminId)
        {
            var author = await context.T011authors.FirstOrDefaultAsync(m => m.Id == authorId);
            if (author != null && author.AdministratorId == null)
            {
                author.AdministratorId = adminId;
                await context.SaveChangesAsync();
            }

        }




        /// <summary>
        /// 根据管理员Id,返回被其管理的作者
        /// </summary>
        /// <param name="adminId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T011author>> GetAllByAdminIdAsync(Guid adminId)
        {
            return await context.T011authors.Where(m => m.AdministratorId == adminId).ToListAsync();
        }

    }
}
